package com.yeban.javase.day19.test.test3;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Desc TODO
 * @Author yeban
 * @Date 2025/11/3
 */
public class ThreadPoolTCPClient {

    public static void main(String[] args) {
        // 创建自定义线程池
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                2, 3,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3)
        );

        System.out.println("---------- TCPClient ----------");
        Socket socket = null;
        try {
            // 启动服务端
            socket = new Socket(InetAddress.getLocalHost(),8123);
            // 等待接入客户端
            System.out.println("成功接入客户端：" + socket.getRemoteSocketAddress());

            // 同时启动收/发线程
            pool.execute(new ClientReader(socket));
            pool.execute(new ClientWriter(socket));
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 关闭线程池
            pool.shutdown();
        }
    }
}

/**
 * 读取服务端的消息
 */
class ClientReader implements Runnable {

    private final Socket socket;

    ClientReader(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try(BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {
            String msg = null;
            while((msg = br.readLine()) != null) {
                if(msg.equals("exit")) {
                    System.out.println("服务端已断开连接~");
                    break;
                } else {
                    System.out.println("服务器说：" + msg);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

/**
 * 客户端写出消息到服务端
 */
class ClientWriter implements Runnable {

    private final Socket socket;

    ClientWriter(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        // 设置参数为true后：这会在调用 println() 后立即 flush（实时发送）。
        try(PrintWriter pw = new PrintWriter(socket.getOutputStream(), true);) {
            Scanner sc = new Scanner(System.in);
            while(true) {
                String msg = sc.nextLine();
                if(msg.equals("exit")) {
                    System.out.println("客户端主动下线了~");
                    break;
                } else {
                    pw.println(msg);
                    pw.flush();
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
